{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 1. 用Pytorch构建两个模型，分别是回归预测和分类预测。要求定义成类的形式。",
   "id": "5a6d218f70016135"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-11-03T03:30:19.170602Z",
     "start_time": "2025-11-03T03:30:19.154167Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch as t\n",
    "import torch.nn as nn\n",
    "\n",
    "\n",
    "class RegressionModel(nn.Module):\n",
    "    def __init__(self, input_dim, hidden_dims=[128, 64, 32]):\n",
    "        super(RegressionModel, self).__init__()\n",
    "        layers = []\n",
    "        prev_dim = input_dim\n",
    "        for dim in hidden_dims:\n",
    "            layers.append(nn.Linear(prev_dim, dim))\n",
    "            layers.append(nn.ReLU())  # 使用ReLU激活函数\n",
    "            layers.append(nn.BatchNorm1d(dim))  # 批标准化加速训练\n",
    "            layers.append(nn.Dropout(0.2))  # Dropout防止过拟合\n",
    "            prev_dim = dim\n",
    "        layers.append(nn.Linear(prev_dim, 1))\n",
    "\n",
    "        self.model = nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self, x):\n",
    "        return self.model(x)\n",
    "\n",
    "\n",
    "class ClassificationModel(nn.Module):\n",
    "    def __init__(self, input_dim, num_classes, hidden_dims=[256, 128, 64]):\n",
    "        super(ClassificationModel, self).__init__()\n",
    "        # 构建神经网络层\n",
    "        layers = []\n",
    "        prev_dim = input_dim\n",
    "        for dim in hidden_dims:\n",
    "            layers.append(nn.Linear(prev_dim, dim))\n",
    "            layers.append(nn.LeakyReLU(0.1))\n",
    "            layers.append(nn.BatchNorm1d(dim))\n",
    "            layers.append(nn.Dropout(0.3))\n",
    "            prev_dim = dim\n",
    "        layers.append(nn.Linear(prev_dim, num_classes))\n",
    "\n",
    "        self.model = nn.Sequential(*layers)\n",
    "\n",
    "    def forward(self, x):\n",
    "        logits = self.model(x)\n",
    "        return logits\n",
    "\n",
    "\n",
    "# 使用示例\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    reg_model = RegressionModel(input_dim=10)\n",
    "    reg_input = t.randn(32, 10)  # 32个样本，每个样本10维特征\n",
    "    reg_output = reg_model(reg_input)\n",
    "    print(f\"回归模型输出形状: {reg_output.shape}\")  # 应为(32, 1)\n",
    "\n",
    "\n",
    "    cls_model = ClassificationModel(input_dim=20, num_classes=5)\n",
    "    cls_input = t.randn(32, 20)\n",
    "    cls_output = cls_model(cls_input)\n",
    "    print(f\"分类模型输出形状: {cls_output.shape}\")\n",
    "    print(f\"分类概率分布: \\n{t.nn.functional.softmax(cls_output, dim=1)[:2]}\")  # 前2个样本的概率分布"
   ],
   "id": "7834f6f3b20eed9a",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "回归模型输出形状: torch.Size([32, 1])\n",
      "分类模型输出形状: torch.Size([32, 5])\n",
      "分类概率分布: \n",
      "tensor([[0.1088, 0.1092, 0.2502, 0.3141, 0.2178],\n",
      "        [0.0828, 0.2171, 0.2142, 0.1958, 0.2900]], grad_fn=<SliceBackward0>)\n"
     ]
    }
   ],
   "execution_count": 7
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 2. 定义一个train函数，在函数中完成对模型的训练，\n",
    "```\n",
    "def train(model, train_data_loader, epochs):\n",
    "```\n",
    "返回训练好的模型"
   ],
   "id": "332ad388bd79ef1a"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-11-03T01:39:36.672339Z",
     "start_time": "2025-11-03T01:39:36.665257Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch.optim as optim\n",
    "import torch.nn as nn\n",
    "\n",
    "\n",
    "def train(model, train_data_loader, epochs):\n",
    "    if isinstance(model, RegressionModel):\n",
    "        criterion = nn.MSELoss()\n",
    "    elif isinstance(model, ClassificationModel):\n",
    "        criterion = nn.CrossEntropyLoss()\n",
    "    else:\n",
    "        raise ValueError(\"模型类型不支持\")\n",
    "\n",
    "\n",
    "    optimizer = optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-5)\n",
    "\n",
    "\n",
    "    model.train()\n",
    "    for epoch in range(epochs):\n",
    "        running_loss = 0.0\n",
    "        correct = 0\n",
    "        total = 0\n",
    "\n",
    "        for inputs, targets in train_data_loader:\n",
    "            optimizer.zero_grad()\n",
    "            outputs = model(inputs)\n",
    "\n",
    "            if isinstance(model, RegressionModel):\n",
    "\n",
    "                loss = criterion(outputs.squeeze(), targets.float())\n",
    "            else:\n",
    "\n",
    "                loss = criterion(outputs, targets.long())\n",
    "                _, predicted = torch.max(outputs.data, 1)\n",
    "                total += targets.size(0)\n",
    "                correct += (predicted == targets).sum().item()\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            running_loss += loss.item()\n",
    "\n",
    "        avg_loss = running_loss / len(train_data_loader)\n",
    "        print(f\"Epoch {epoch+1}/{epochs} - Average Loss: {avg_loss:.6f}\")\n",
    "        if isinstance(model, ClassificationModel):\n",
    "            acc = 100 * correct / total\n",
    "            print(f\"Training Accuracy: {acc:.2f}%\\n\")\n",
    "    return model"
   ],
   "id": "8ec1539df6f970e4",
   "outputs": [],
   "execution_count": 5
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "",
   "id": "b74f557a64aa3723"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 3. 定义一个eval函数，在函数中完成对模型的评估，\n",
    "```\n",
    "def eval(model, test_data_loader, eval_metrics):\n",
    "```\n",
    "注意eval_metrics是一个函数，根据不同类型的任务传入不同函数对模型进行评估：\n",
    "- 回归 MSE\n",
    "- 分类 准确率"
   ],
   "id": "900bce31e0405739"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-11-03T03:38:13.838616Z",
     "start_time": "2025-11-03T03:38:13.821102Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "\n",
    "def eval(model, test_data_loader, eval_metrics):\n",
    "    model.eval()\n",
    "    all_outputs = []\n",
    "    all_targets = []\n",
    "\n",
    "    with torch.no_grad():\n",
    "        for inputs, targets in test_data_loader:\n",
    "            outputs = model(inputs)\n",
    "            all_outputs.append(outputs)\n",
    "            all_targets.append(targets)\n",
    "    all_outputs = torch.cat(all_outputs, dim=0)\n",
    "    all_targets = torch.cat(all_targets, dim=0)\n",
    "\n",
    "    if isinstance(model, RegressionModel):\n",
    "        predictions = all_outputs\n",
    "        targets = all_targets.float()\n",
    "    else:\n",
    "        _, predictions = torch.max(all_outputs, 1)\n",
    "        targets = all_targets.long()\n",
    "\n",
    "    score = eval_metrics(predictions, targets)\n",
    "\n",
    "    if isinstance(model, RegressionModel):\n",
    "        print(f\"测试集 MSE: {score:.6f}\")\n",
    "    else:\n",
    "        print(f\"测试集准确率: {score:.2f}%\")\n",
    "\n",
    "    return score\n",
    "\n",
    "def mse_metric(predictions, targets):\n",
    "\n",
    "    return nn.MSELoss()(predictions, targets).item()\n",
    "\n",
    "def accuracy_metric(predictions, targets):\n",
    "\n",
    "    correct = (predictions == targets).sum().item()\n",
    "    total = targets.size(0)\n",
    "    return 100.0 * correct / total\n",
    "\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "\n",
    "    from torch.utils.data import DataLoader, TensorDataset\n",
    "\n",
    "\n",
    "    print(\"=== 回归模型评估 ===\")\n",
    "    reg_model = RegressionModel(input_dim=10)\n",
    "    reg_X = torch.randn(100, 10)\n",
    "    reg_y = torch.randn(100, 1)\n",
    "    reg_dataset = TensorDataset(reg_X, reg_y)\n",
    "    reg_loader = DataLoader(reg_dataset, batch_size=32)\n",
    "\n",
    "    reg_score = eval(reg_model, reg_loader, mse_metric)\n",
    "\n",
    "    print(\"\\n=== 分类模型评估 ===\")\n",
    "\n",
    "    cls_model = ClassificationModel(input_dim=20, num_classes=5)\n",
    "    cls_X = torch.randn(100, 20)\n",
    "    cls_y = torch.randint(0, 5, (100,))\n",
    "    cls_dataset = TensorDataset(cls_X, cls_y)\n",
    "    cls_loader = DataLoader(cls_dataset, batch_size=32)\n",
    "\n",
    "    cls_score = eval(cls_model, cls_loader, accuracy_metric)"
   ],
   "id": "df7b0a476bc09324",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "=== 回归模型评估 ===\n",
      "测试集 MSE: 0.804827\n",
      "\n",
      "=== 分类模型评估 ===\n",
      "测试集准确率: 30.00%\n"
     ]
    }
   ],
   "execution_count": 59
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
